<?php
/**
 * curl类
 *
 * 自定义网络连接接口代替curl
 * @package Z-BlogPHP
 * @subpackage ClassLib/Network/Networkcurl 网络连接
 */
class Networkcurl implements iNetwork
{
  private $readyState = 0; //状态
  private $responseBody = null; //返回的二进制
  private $responseStream = null; //返回的数据流
  private $responseText = ''; //返回的数据
  private $responseXML = null; //尝试把responseText格式化为XMLDom
  private $status = 0; //状态码
  private $statusText = ''; //状态码文本
  private $responseVersion = ''; //返回的HTTP版体
  private $option = array();
  private $url = '';
  private $postdata = array();
  private $httpheader = array();
  private $responseHeader = array();
  private $parsed_url = array();
  private $timeout = 30;
  private $errstr = '';
  private $errno = 0;
  private $ch = null;
  private $isgzip = false;
  private $maxredirs = 0;
  private $__isBinary = false;
  /**
   * @ignore
   */
  public function __construct()
  {
    //$this->ch = curl_init();
  }
  /**
   * @param $property_name
   * @param $value
   * @throws Exception
   */
  public function __set($property_name, $value)
  {
    throw new Exception($property_name . ' readonly');
  }
  /**
   * @param $property_name
   * @return mixed
   */
  public function __get($property_name)
  {
    if (strtolower($property_name) == 'responsexml') {
      $w = new DOMDocument();
      return $w->loadXML($this->responseText);
    } elseif (strtolower($property_name) == 'scheme' || strtolower($property_name) == 'host' || strtolower($property_name) == 'port' || strtolower($property_name) == 'user' || strtolower($property_name) == 'pass' || strtolower($property_name) == 'path' || strtolower($property_name) == 'query' || strtolower($property_name) == 'fragment') {
      if (isset($this->parsed_url[strtolower($property_name)])) {
        return $this->parsed_url[strtolower($property_name)];
      } else {
        return null;
      }
    } else {
      return $this->$property_name;
    }
  }
  /**
   * 取消
   */
  public function abort()
  {
  }
  /**
   * @return string
   */
  public function getAllResponseHeaders()
  {
    return implode("\r\n", $this->responseHeader);
  }
  /**
   * 获取返回头
   * @param $bstrHeader
   * @return string
   */
  public function getResponseHeader($bstrHeader)
  {
    $name = strtolower($bstrHeader);
    foreach ($this->responseHeader as $w) {
      if (strtolower(substr($w, 0, strpos($w, ':'))) == $name) {
        return substr(strstr($w, ': '), 2);
      }
    }
    return '';
  }
  /**
   * 链接远程接口
   * @param $bstrMethod
   * @param $bstrUrl
   * @param bool $varAsync
   * @param string $bstrUser
   * @param string $bstrPassword
   * @return bool
   * @throws Exception
   */
  public function open($bstrMethod, $bstrUrl, $varAsync = true, $bstrUser = '', $bstrPassword = '')
  {
    //Async无用
    $this->reinit();
    $method                 = strtoupper($bstrMethod);
    $this->option['method'] = $method;
    $this->parsed_url       = parse_url($bstrUrl);
    if (!$this->parsed_url) {
      throw new Exception('URL Syntax Error!');
    }
    if (!isset($this->parsed_url['port'])) {
      if (isset($this->parsed_url['scheme']) && $this->parsed_url['scheme'] == 'https') {
        $this->parsed_url['port'] = 443;
      } else {
        $this->parsed_url['port'] = 80;
      }
    }
    curl_setopt($this->ch, CURLOPT_URL, $bstrUrl);
    curl_setopt($this->ch, CURLOPT_HEADER, 1);
    curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, 1);
    //curl_setopt($this->ch, CURLOPT_REFERER, 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
    curl_setopt($this->ch, CURLOPT_POST, ($method == 'POST' ? 1 : 0));
    return true;
  }
  /**
   * 设置超时时间
   * @param $resolveTimeout
   * @param $connectTimeout
   * @param $sendTimeout
   * @param $receiveTimeout
   */
  public function setTimeOuts($resolveTimeout, $connectTimeout, $sendTimeout, $receiveTimeout)
  {
    curl_setopt($this->ch, CURLOPT_CONNECTTIMEOUT, $connectTimeout);
    curl_setopt($this->ch, CURLOPT_TIMEOUT, $resolveTimeout);
  }
  /**
   * 发送数据
   * @param string $varBody
   */
  public function send($varBody = '')
  {
    $data = $varBody;
    if (is_array($data)) {
      $data = http_build_query($data);
    }
    curl_setopt($this->ch, CURLOPT_HTTPHEADER, $this->httpheader);
    if ($this->option['method'] == 'POST') {
      if ($data == '') {
        $data = $this->postdata;
      }
      if ($this->__isBinary) {
        curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, 'POST');
      } else {
        curl_setopt($this->ch, CURLOPT_POST, 1);
      }
      curl_setopt($this->ch, CURLOPT_POSTFIELDS, $data);
    }
    curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
    if ($this->maxredirs > 0) {
      if (ini_get("safe_mode") == false && ini_get("open_basedir") == false) {
        curl_setopt($this->ch, CURLOPT_MAXREDIRS, $this->maxredirs);
        curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, true);
      }
    }
    if ($this->isgzip == true) {
      curl_setopt($this->ch, CURLOPT_ENCODING, 'gzip');
    }
    curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, false);
    $result               = curl_exec($this->ch);
    $header_size          = curl_getinfo($this->ch, CURLINFO_HEADER_SIZE);
    $this->responseHeader = explode("\r\n", substr($result, 0, $header_size - 4));
    $this->responseText   = substr($result, $header_size);
    curl_close($this->ch);
    foreach ($this->responseHeader as $key => $value) {
      if (strpos($value, 'HTTP/') === 0) {
        if (isset($this->responseHeader[$key])) {
          $this->statusText = $this->responseHeader[$key];
          $a                = explode(' ', $this->statusText);
          if (isset($a[0])) {
            $this->responseVersion = $a[0];
          }
          if (isset($a[1])) {
            $this->status = $a[1];
          }
          unset($this->responseHeader[$key]);
        }
      }
    }
  }
  /**
   * 设置请求HTTP头
   * @param $bstrHeader
   * @param $bstrValue
   * @param bool $append
   * @return bool
   */
  public function setRequestHeader($bstrHeader, $bstrValue, $append = false)
  {
    if ($append == false) {
      $this->httpheader[$bstrHeader] = $bstrHeader . ': ' . $bstrValue;
    } else {
      if (isset($this->httpheader[$bstrHeader])) {
        $this->httpheader[$bstrHeader] = $this->httpheader[$bstrHeader] . $bstrValue;
      } else {
        $this->httpheader[$bstrHeader] = $bstrHeader . ': ' . $bstrValue;
      }
    }
    return true;
  }
  /**
   * 添加数据
   * @param string $bstrItem 参数
   * @param mixed $bstrValue 值
   */
  public function add_postdata($bstrItem, $bstrValue)
  {
    $this->postdata[$bstrItem] = $bstrValue;
  }
  /**
   * @param string $name
   * @param string $entity
   * @return mixed
   */
  public function addBinary($name, $entity, $filename = null, $mime = '')
  {
    global $zbp;
    $this->__isBinary = true;
    if (!is_file($entity)) {
      $filename             = ($filename === null ? $name : $filename);
      $key                  = "$name\"; filename=\"$filename\"\r\nContent-Type: " . ($mime == '' ? 'application/octet-stream' : $mime) . "\r\n";
      $this->postdata[$key] = $entity;
      return;
    }
    if ($mime == '') {
      if (function_exists('mime_content_type')) {
        $mime = mime_content_type($entity);
      } elseif (function_exists('finfo_open')) {
        $finfo = finfo_open(FILEINFO_MIME);
        $mime  = finfo_file($finfo, $name);
        finfo_close($finfo);
      } else {
        $mime = 'application/octet-stream';
      }
    }
    $filename = ($filename === null ? basename($entity) : $filename);
    if (class_exists('CURLFile')) {
      $this->postdata[$name] = new CURLFile($entity, $mime, $filename);
      return;
    }
    $entity = realpath($entity);
    $value  = "@{$entity}";
    if (!empty($mime)) {
      $value .= ';type=' . $mime;
    }
    $value .= ';filename=' . $filename;
    $this->postdata[$name] = $value;
  }
  /**
   * @param string $name
   * @param string $entity
   * @return mixed
   */
  public function addText($name, $entity)
  {
    return $this->add_postdata($name, $entity);
  }
  /**
   * 重置
   */
  private function reinit()
  {
    // global $zbp;
    $this->readyState     = 0; //状态
    $this->responseBody   = null; //返回的二进制
    $this->responseStream = null; //返回的数据流
    $this->responseText   = ''; //返回的数据
    $this->responseXML    = null; //尝试把responseText格式化为XMLDom
    $this->status         = 0; //状态码
    $this->statusText     = ''; //状态码文本
    $this->__isBinary     = false;
    $this->option         = array();
    $this->url            = '';
    $this->postdata       = array();
    $this->httpheader     = array();
    $this->responseHeader = array();
    $this->parsed_url     = array();
    $this->timeout        = 30;
    $this->errstr         = '';
    $this->errno          = 0;
    $this->ch             = curl_init();
    // $this->setRequestHeader('User-Agent', 'Mozilla/5.0 (' . $zbp->cache->system_environment . ') Z-BlogPHP/' . $GLOBALS['blogversion']);
    $this->setMaxRedirs(1);
  }
  /**
   * 启用Gzip
   */
  public function enableGzip()
  {
    if (extension_loaded('zlib')) {
      $this->isgzip = true;
    }
  }
  /**
   * @param int $n
   */
  public function setMaxRedirs($n = 0)
  {
    $this->maxredirs = (int) $n;
  }
}
